#include "config.h"

#include <cstdio>
#include <iostream>
#include <string>

using namespace cfg;

// 示例：从 JSON/YAML 文件加载 Schema 与配置（包含 include 机制）
// - 需要在构建时启用 CFG_ENABLE_YAML。
// - 动态生成临时文件：一个 schema.yaml 和两个数据文件（其中 data.yaml 通过 include 引入片段）。
// - 展示：Builder::load_json_schema_file + Builder::include_file + freeze 校验。

// 函数：创建测试数据文件，返回文件路径（相对于当前工作目录）。
static std::string
create_file(const std::string & filename, const char * content)
{
    FILE * fp = std::fopen(filename.c_str(), "w");
    if (!fp)
        return {};
    std::fputs(content, fp);
    std::fclose(fp);
    return filename;
}

int
main()
{
#ifndef CFG_ENABLE_YAML
    std::cerr << "CFG_ENABLE_YAML not enabled\n";
    return 1;
#else
    // 1) 写入一个 schema.yaml（object + properties + enum/pattern/min/max）
    const std::string schema_path =
        create_file("schema_example.yaml",
                    "type: object\n"
                    "properties:\n"
                    "  mode:\n"
                    "    type: string\n"
                    "    enum: [dev, prod]\n"
                    "  email:\n"
                    "    type: string\n"
                    "    pattern: '^[\\w.-]+@[\\w.-]+\\.[A-Za-z]{2,}$'\n"
                    "  timeout:\n"
                    "    type: number\n"
                    "    minimum: 1\n"
                    "    maximum: 5\n"
                    "required: [mode, email, timeout]\n");

    // 2) 写入一个片段文件 part.yaml，被主文件 include
    const std::string part_path = create_file("part.yaml",
                                              "db:\n"
                                              "  host: localhost\n"
                                              "  port: 5432\n");

    // 3) 写入一个主配置文件 data.yaml，包含 include 指令（按你的 include_file 设计，这里直接通过
    // include_file 加载文件）
    //    示例中我们使用 Builder::include_file 连续包含两个文件：data.yaml（对象根）与 JSON
    //    标量（非对象根兜底）。
    const std::string data_path = create_file("data.yaml",
                                              "a: 1\n"
                                              "arr: [10, 20]\n");
    const std::string scalar_json = create_file("value.json", "42\n");

    // 4) 构建并加载
    Builder builder;
    builder.load_json_schema_file(schema_path);

    // 路径解析策略：相对当前目录
    builder.set_include_path_mode(IncludePathMode::AsProvided);

    // 包含对象根：data.yaml 与 part.yaml
    builder.include_file(data_path).include_file(part_path).include_file(
        scalar_json); // 非对象根兜底写到 key "value"

    // 设置满足 schema 的值
    builder.set("mode", std::string("dev"));
    builder.set("email", std::string("user@example.com"));
    builder.set("timeout", double{3.5});

    auto frozen = builder.freeze();
    if (!frozen)
    {
        std::cerr << "validation failed: " << frozen.error().size() << " error(s)\n";
        for (const auto & e : frozen.error())
            std::cerr << "[" << static_cast<int>(e.code) << "] " << e.message << "\n";
        return 1;
    }

    View v(*frozen);
    auto host = v.lookup("db.host").and_then([](const View & sv) { return sv.get_string(); });
    auto port = v.lookup("db.port").and_then([](const View & sv) { return sv.get_int64(); });
    auto val = v.lookup("value").and_then([](const View & sv) { return sv.get_int64(); });

    if (host && port && val)
        std::cout << "Loaded: host=" << *host << ", port=" << *port << ", value=" << *val << "\n";
    else
        std::cout << "Loaded with missing fields.\n";

    return 0;
#endif
}
